#!/usr/bin/env pwsh

<#
.SYNOPSIS
    Service Management Script - Interactive tool for managing Docker services

.DESCRIPTION
    This script provides an interactive interface for users to select operation mode (start/stop) and services to operate on.
    Features include: loop menu, service status display, quit option, and automatic directory creation for MySQL and Redis data volumes.
    MySQL and Redis services now automatically check and create data directories if they don't exist.

.EXAMPLE
    .\manage_services.ps1

.NOTES
    Author: AI Assistant
    Date: 2024-01-21
    Updated: $(Get-Date -Format "yyyy-MM-dd") - Added support for automatic directory creation in MySQL and Redis services
#>

# Service script path list
$SERVICE_SCRIPTS = @(
    ".\01manage_mysql.ps1",
    ".\02manage_redis.ps1",
    ".\03manage_node-server-prod.ps1",
    ".\04manage_frontend-prod.ps1",
    ".\05manage_sysadmin-prod.ps1",
    ".\06manage_springboot-server.ps1",
    ".\07manage_python-server.ps1",
    ".\08manage_fastapi-server.ps1"
)

# Service name list (for display)
$SERVICE_NAMES = @(
    "MySQL",
    "Redis",
    "Node.js Server",
    "Frontend",
    "SysAdmin",
    "SpringBoot Server",
    "Python Server",
    "FastAPI Server"
)

# Ensure service script paths and names count match
if ($SERVICE_SCRIPTS.Count -ne $SERVICE_NAMES.Count) {
    Write-Host "Error: Service script paths and names count do not match!" -ForegroundColor Red
    exit 1
}

# Check service status
function Get-ServiceStatus {
    <#
    .SYNOPSIS
        Check the running status of a Docker service
    
    .DESCRIPTION
        Uses docker ps to check if a service is running
    
    .PARAMETER ServiceName
        The name of the service to check
    
    .RETURNS
        Returns "Running" if service is running, otherwise "Stopped"
    #>
    param (
        [string]$ServiceName
    )
    
    try {
        # Use docker ps with filter to check if service is running
        $result = docker ps --filter "name=$ServiceName" --format "{{.Names}}"
        if ($result -match $ServiceName) {
            return "Running"
        } else {
            return "Stopped"
        }
    } catch {
        return "Unknown"
    }
}

# Get operation mode
function Get-OperationMode {
    <#
    .SYNOPSIS
        Get user-selected operation mode (start or stop) or quit
    
    .DESCRIPTION
        Prompt user to enter operation mode, accept start, stop, or q (quit), and validate
    
    .RETURNS
        Returns user-selected operation mode ("start", "stop") or "quit"
    #>
    do {
        Write-Host "Please select operation mode:" -ForegroundColor Yellow
        Write-Host "1. start - Start services"
        Write-Host "2. stop - Stop services"
        Write-Host "q. Quit - Exit the program"
        $modeInput = Read-Host -Prompt "Please enter operation mode (start/stop/q) or corresponding number"
        
        # Convert input to lowercase and handle numeric input
        $modeInput = $modeInput.ToLower().Trim()
        if ($modeInput -eq "1" -or $modeInput -eq "start") {
            $operationMode = "start"
            break
        } elseif ($modeInput -eq "2" -or $modeInput -eq "stop") {
            $operationMode = "stop"
            break
        } elseif ($modeInput -eq "q" -or $modeInput -eq "quit") {
            $operationMode = "quit"
            break
        } else {
            Write-Host "Error: Invalid operation mode. Please enter 'start', 'stop', or 'q'." -ForegroundColor Red
        }
    } while ($true)
    
    return $operationMode
}

# Show service list with status
function Show-ServiceList {
    <#
    .SYNOPSIS
        Display all available services list with running status
    
    .DESCRIPTION
        Format and display all services with their indices and running status for easy user selection
    #>
    Write-Host "`nAvailable Services List:" -ForegroundColor Yellow
    Write-Host "----------------------------------------" -ForegroundColor Yellow
    Write-Host "Index  Service Name           Status"
    Write-Host "----------------------------------------" -ForegroundColor Yellow
    
    for ($i = 0; $i -lt $SERVICE_NAMES.Count; $i++) {
        $index = $i + 1
        $serviceName = $SERVICE_NAMES[$i]
        
        # Map display name to Docker container name for status checking
        $dockerName = ""
        switch ($serviceName) {
            "MySQL" { $dockerName = "mysql" }
            "Redis" { $dockerName = "redis" }
            "Node.js Server" { $dockerName = "node-server" }
            "Frontend" { $dockerName = "frontend" }
            "SysAdmin" { $dockerName = "sysadmin" }
            "SpringBoot Server" { $dockerName = "springboot-server" }
            "Python Server" { $dockerName = "python-server" }
            "FastAPI Server" { $dockerName = "fastapi-server" }
            default { $dockerName = $serviceName.ToLower().Replace(" ", "-") }
        }
        
        $status = Get-ServiceStatus -ServiceName $dockerName
        
        # Color code status
        $statusColor = if ($status -eq "Running") { "Green" } elseif ($status -eq "Stopped") { "Red" } else { "Yellow" }
        
        # Format output with alignment
        Write-Host ("{0,-6} {1,-22} [{2}]" -f $index, $serviceName, $status) -ForegroundColor $statusColor
    }
    
    Write-Host "----------------------------------------" -ForegroundColor Yellow
    Write-Host "Tip: Enter service index (multiple indices separated by commas) or enter 'A' to select all services"
}

# Get selected services
function Get-SelectedServices {
    <#
    .SYNOPSIS
        Get user-selected service indices with quit option
    
    .DESCRIPTION
        Prompt user to enter service indices, which can be a single index, multiple indices (comma-separated), or 'A' (all), with 'q' to quit
    
    .RETURNS
        Returns array of selected service indices
    #>
    do {
        Show-ServiceList
        $selectionInput = Read-Host -Prompt "Please enter service indices to $operationMode or 'q' to quit"
        
        # Handle quit option
        if ($selectionInput.ToLower().Trim() -eq "q") {
            Write-Host "`nThank you for using Service Management Tool. Goodbye!" -ForegroundColor Cyan
            exit 0
        }
        
        # Process select all
        if ($selectionInput.ToUpper().Trim() -eq "A") {
            return 0..($SERVICE_NAMES.Count - 1)
        }
        
        # Process multiple selections (comma-separated)
        $selectedIndices = @()
        $validSelection = $true
        
        try {
            $selections = $selectionInput.Split(',') | ForEach-Object { $_.Trim() }
            
            foreach ($sel in $selections) {
                # Validate if it's a valid number
                if (-not [int]::TryParse($sel, [ref]$null)) {
                    Write-Host "Error: '$sel' is not a valid number" -ForegroundColor Red
                    $validSelection = $false
                    break
                }
                
                $index = [int]$sel - 1
                
                # Validate index range
                if ($index -lt 0 -or $index -ge $SERVICE_NAMES.Count) {
                    Write-Host "Error: Index $sel is out of valid range (1-$($SERVICE_NAMES.Count))" -ForegroundColor Red
                    $validSelection = $false
                    break
                }
                
                $selectedIndices += $index
            }
            
            # Check for duplicate selections
            if ($selectedIndices.Count -gt ($selectedIndices | Select-Object -Unique).Count) {
                Write-Host "Error: Duplicate service indices exist" -ForegroundColor Red
                $validSelection = $false
            }
            
            # Check if at least one service is selected
            if ($selectedIndices.Count -eq 0) {
                Write-Host "Error: Please select at least one service" -ForegroundColor Red
                $validSelection = $false
            }
        } catch {
            Write-Host "Error: Input format is incorrect, please use commas to separate multiple indices" -ForegroundColor Red
            $validSelection = $false
        }
        
        if ($validSelection) {
            return $selectedIndices
        }
    } while ($true)
}

# Execute service operation
function Execute-ServiceOperation {
    <#
    .SYNOPSIS
        Execute start or stop operation for a single service
    
    .DESCRIPTION
        Execute start or stop operation for the corresponding service script based on provided index and operation mode
    
    .PARAMETER ServiceIndex
        Service index in the list
    
    .PARAMETER OperationMode
        Operation mode (start or stop)
    
    .RETURNS
        Whether the operation was successful
    #>
    param (
        [int]$ServiceIndex,
        [string]$OperationMode
    )
    
    $serviceName = $SERVICE_NAMES[$ServiceIndex]
    $scriptPath = $SERVICE_SCRIPTS[$ServiceIndex]
    
    Write-Host "`n$OperationMode-ing $serviceName..." -ForegroundColor Yellow
    
    # Check if script file exists
    if (-not (Test-Path $scriptPath)) {
        Write-Host "Error: Service script not found: $scriptPath" -ForegroundColor Red
        return $false
    }
    
    try {
        # Get the full path to the script
        $fullScriptPath = (Resolve-Path $scriptPath).Path
        
        # Get the parent directory path (where the service scripts are located)
        $serviceScriptDir = Split-Path -Parent $fullScriptPath
        
        # Execute service script with correct working directory and absolute path
        # Use separate arguments for better handling of paths with spaces
        # The service script will automatically handle directory creation for MySQL and Redis
        $result = Start-Process -FilePath "powershell.exe" -ArgumentList "-ExecutionPolicy", "Bypass", "-File", "$fullScriptPath", "$OperationMode" -WorkingDirectory $serviceScriptDir -Wait -NoNewWindow -PassThru
        
        if ($result.ExitCode -eq 0) {
            Write-Host "Success: $serviceName has been successfully $OperationMode-ed" -ForegroundColor Green
            return $true
        } else {
            Write-Host "Failed: $serviceName $OperationMode failed, exit code: $($result.ExitCode)" -ForegroundColor Red
            return $false
        }
    } catch {
        Write-Host "Error: Exception occurred while executing ${OperationMode}: $_" -ForegroundColor Red
        return $false
    }
}

# Main function with loop menu
function Main {
    # Welcome message
    Write-Host "===================================" -ForegroundColor Cyan
    Write-Host "      Service Management Tool      " -ForegroundColor Cyan
    Write-Host "===================================" -ForegroundColor Cyan
    Write-Host "Type 'q' at any prompt to quit." -ForegroundColor Gray
    
    # Main loop
    while ($true) {
        Write-Host "`n-----------------------------------" -ForegroundColor Cyan
        
        # Get operation mode
        $operationMode = Get-OperationMode
        
        # Check if user wants to quit
        if ($operationMode -eq "quit") {
            Write-Host "`nThank you for using Service Management Tool. Goodbye!" -ForegroundColor Cyan
            break
        }
        
        Write-Host "`nSelected operation mode: $operationMode" -ForegroundColor Green
        
        # Get user-selected services
        $selectedIndices = Get-SelectedServices
        
        # Show selected services
        Write-Host "`nSelected services:" -ForegroundColor Green
        foreach ($index in $selectedIndices) {
            Write-Host "- $($SERVICE_NAMES[$index])"
        }
        
        # Confirm operation
        Write-Host "`n===================================" -ForegroundColor Yellow
        Write-Host "About to perform $operationMode operation on the above services" -ForegroundColor Yellow
        
        do {
            $confirm = Read-Host -Prompt "Confirm execution? (Y/N/q)"
            $confirm = $confirm.ToUpper().Trim()
            
            if ($confirm -eq "N") {
                Write-Host "`nOperation cancelled" -ForegroundColor Yellow
                # Continue to next iteration of main loop
                continue
            } elseif ($confirm -eq "Q") {
                Write-Host "`nThank you for using Service Management Tool. Goodbye!" -ForegroundColor Cyan
                return
            } elseif ($confirm -ne "Y") {
                Write-Host "Please enter 'Y' to confirm, 'N' to cancel, or 'Q' to quit" -ForegroundColor Red
            }
        } while ($confirm -ne "Y")
        
        # Execute operations
        $successCount = 0
        $failureCount = 0
        
        Write-Host "`n===================================" -ForegroundColor Cyan
        Write-Host "Starting $operationMode operations..." -ForegroundColor Cyan
        Write-Host "===================================" -ForegroundColor Cyan
        
        # 对于停止操作，按照倒序执行（从最后一个服务到第一个服务）
        if ($operationMode -eq "stop") {
            Write-Host "Stopping services in reverse order for dependency management..." -ForegroundColor Yellow
            $executionIndices = $selectedIndices | Sort-Object -Descending
        } else {
            # 对于启动操作，保持原顺序
            $executionIndices = $selectedIndices
        }
        
        foreach ($index in $executionIndices) {
            $result = Execute-ServiceOperation -ServiceIndex $index -OperationMode $operationMode
            if ($result) {
                $successCount++
            } else {
                $failureCount++
            }
        }
        
        # Show execution result summary
        Write-Host "`n===================================" -ForegroundColor Cyan
        Write-Host "Operation completed!" -ForegroundColor Cyan
        Write-Host "Success: $successCount services" -ForegroundColor Green
        if ($failureCount -gt 0) {
            Write-Host "Failed: $failureCount services" -ForegroundColor Red
        }
        Write-Host "===================================" -ForegroundColor Cyan
        
        # Pause before returning to main menu
        Write-Host "`nPress Enter to continue..." -ForegroundColor Gray
        Read-Host
    }
}

# Run main function
Main